#ifndef OHOS_RIVE_CANVAS_RENDERER_H
#define OHOS_RIVE_CANVAS_RENDERER_H

#include "../helpers/exception_handler.h"
#include "../helpers/general.h"
#include "rive/renderer.hpp"
#include <native_drawing/drawing_canvas.h>
#include <native_drawing/drawing_surface.h>

namespace ohos_rive {
class CanvasRenderer : public rive::Renderer {
protected:
    OH_Drawing_Canvas *m_ohCanvas = nullptr;
    int m_width = -1;
    int m_height = -1;

private:
    static OH_Drawing_Canvas *GetCanvas(OH_Drawing_Surface *surface)
    {
        return OH_Drawing_SurfaceGetCanvas(surface);
    }

    static void Clear(OH_Drawing_Canvas *canvas)
    {
        OH_Drawing_CanvasClear(canvas, 0);
    }

public:
    ~CanvasRenderer() override
    {
        assert(m_ohCanvas == nullptr);
    }
    void save() override;
    void restore() override;
    void transform(const rive::Mat2D &transform) override;
    void clipPath(rive::RenderPath *path) override;
    void drawPath(rive::RenderPath *path, rive::RenderPaint *paint) override;
    void drawImage(const rive::RenderImage *, rive::ImageSampler options, rive::BlendMode, float opacity) override;
    void drawImageMesh(const rive::RenderImage *,
                       rive::ImageSampler options,
                       rive::rcp<rive::RenderBuffer> vertices_f32,
                       rive::rcp<rive::RenderBuffer> uvCoords_f32,
                       rive::rcp<rive::RenderBuffer> indices_u16,
                       uint32_t vertexCount,
                       uint32_t indexCount,
                       rive::BlendMode,
                       float opacity) override;

    [[nodiscard]] int width() const
    {
        return m_width;
    }
    [[nodiscard]] int height() const
    {
        return m_height;
    }

    void bindCanvas(OH_Drawing_Surface *surface)
    {
        // Old canvas needs to be unbound as it might not be valid anymore.
        assert(m_ohCanvas == nullptr);
        m_ohCanvas = OH_Drawing_SurfaceGetCanvas(surface);
        m_width = OH_Drawing_CanvasGetWidth(m_ohCanvas);
        m_height = OH_Drawing_CanvasGetHeight(m_ohCanvas);
        Clear(m_ohCanvas);
    }

    void unlockAndPost(OH_Drawing_Surface *surface)
    {
        m_width = -1;
        m_height = -1;
        OH_Drawing_CanvasDestroy(m_ohCanvas);
        m_ohCanvas = nullptr;
    }
};
} // namespace ohos_rive

#endif // OHOS_RIVE_CANVAS_RENDERER_H

